﻿using System;
using System.Collections.Generic;
using System.Text;
using Vbyte.SharpOrm.Config;

namespace Vbyte.SharpOrm.SqlDb
{
    /// <summary>
    /// 描述SQL数据表
    /// </summary>
    [Serializable]
    public class SqlTable
    {
        /// <summary>
        /// 表名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 表描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 该数据表所对应的实例类型
        /// </summary>
        public Type InstanceType { get; set; }

        /// <summary>
        /// 表中的列集合
        /// </summary>
        public SqlTableColumn[] Columns { get; set; }


        private SqlIndexConfig[] _index = new SqlIndexConfig[0];

        /// <summary>
        /// 当前表的索引配置
        /// </summary>
        public SqlIndexConfig[] Indexes
        {
            get { return _index; }
            set { _index = value; }
        }

        private SqlConstraint[] _constraints = new SqlConstraint[0];
        /// <summary>
        /// 当前表的约束配置
        /// </summary>
        public SqlConstraint[] Constains
        {
            get { return _constraints; }
            set { _constraints = value; }
        }

        private string[] _primaryKeys = new string[0];
        /// <summary>
        /// 主键集合
        /// </summary>
        public string[] PrimaryKeys
        {
            get { return _primaryKeys; }
            set { _primaryKeys = value; }
        }

        private string[] _identityKeys = new string[0];
        /// <summary>
        /// 标志键集合
        /// </summary>
        public string[] IdentityKeys
        {
            get { return _identityKeys; }
            set { _identityKeys = value; }
        }

        private ForeignKeyAttribute[] _foreignKeys = new ForeignKeyAttribute[0];
        /// <summary>
        /// 外键配置
        /// </summary>
        public ForeignKeyAttribute[] ForeignKeys
        {
            get { return _foreignKeys; }
            set { _foreignKeys = value; }
        }

        /// <summary>
        /// 获取或设置该数据表映射的实例类型
        /// </summary>
        public Type MappingEntryType { get; set; }

        /// <summary>
        /// 获取表中制定列名的数据列
        /// </summary>
        /// <param name="colName">列名</param>
        /// <returns>如果存在指定名称的数据列，则返回该列，否则为null。</returns>
        public SqlTableColumn this[string colName]
        {
            get 
            {
                if (Columns == null || Columns.Length < 1)
                {
                    return null;
                }
                else
                {
                    int cIdx = Array.FindIndex<SqlTableColumn>(Columns, m => m.Name.Equals(colName, StringComparison.InvariantCultureIgnoreCase));
                    return (cIdx != -1) ? Columns[cIdx] : null;
                }
            }
        }
    }

    /// <summary>
    /// 描述SQL表中的列定义
    /// </summary>
    [Serializable]
    public class SqlTableColumn
    {
        /// <summary>
        /// 列表
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 列描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 简介数据类型：如nvarchar(255), decimal(18, 2)
        /// </summary>
        public string DataType { get; set; }

        /// <summary>
        /// 默认值
        /// </summary>
        public object Default { get; set; }

        private bool _isNullable = true;
        /// <summary>
        /// 改列值是否可为null
        /// </summary>
        public bool IsNullable
        {
            get { return _isNullable; }
            set { _isNullable = value; }
        }

        /// <summary>
        /// 是否主键组成部分
        /// </summary>
        public bool IsPrimary { get; set; }

        private bool _isIdentity = false;

        /// <summary>
        /// 是否是标志键组成部分
        /// </summary>
        public bool IsIdentity
        {
            get
            {
                return _isIdentity;
            }
            set
            {
                if (value == true) IsNullable = false;
                _isIdentity = value;
            }
        }

        /// <summary>
        /// 设置列的最大长度
        /// </summary>
        public int? MaxLength { get; set; }

        /// <summary>
        /// 自动增加列的定义
        /// </summary>
        public SqlAutoIncrement AutoIncrement { get; set; }

    }

    /// <summary>
    /// SQL表中的自增列定义
    /// </summary>
    [Serializable]
    public class SqlAutoIncrement
    {
        /// <summary>
        /// 初始化一个以1为种子，增长值为1的自增列定义
        /// </summary>
        public SqlAutoIncrement()
        {
            Seed = 1;
            Step = 1;
        }

        /// <summary>
        /// 初始化一个自增列定义
        /// </summary>
        /// <param name="seed">开始的种子数</param>
        /// <param name="step">递增步长</param>
        public SqlAutoIncrement(int seed, int step)
        {
            Seed = seed;
            Step = step;
        }

        /// <summary>
        /// 种子
        /// </summary>
        /// <value>The seed.</value>
        public int Seed { get; set; }

        /// <summary>
        /// 递增步长
        /// </summary>
        /// <value>The step.</value>
        public int Step { get; set; }

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString()
        {
            return string.Format("({0},{1})", Seed, Step);
        }
    }

    /// <summary>
    /// SQL表中的索引配置
    /// </summary>
    [Serializable]
    public class SqlIndexConfig
    {
        /// <summary>
        /// 创建默认非聚焦、可重复的索引
        /// </summary>
        public SqlIndexConfig()
            : this(null, false, false, false)
        {

        }

        /// <summary>
        /// 创建指定聚焦、重复与否的索引
        /// </summary>
        /// <param name="isUNIQUE">是否不重复</param>
        /// <param name="isCLUSTERED">是否聚焦</param>
        public SqlIndexConfig(bool isUNIQUE, bool isCLUSTERED)
            : this(null, isUNIQUE, isCLUSTERED, false)
        {
        }

        /// <summary>
        /// 创建指定聚焦、重复与否的索引
        /// </summary>
        /// <param name="idxName">索引名称</param>
        /// <param name="isUNIQUE">是否不重复</param>
        /// <param name="isCLUSTERED">是否聚焦</param>
        public SqlIndexConfig(string idxName, bool isUNIQUE, bool isCLUSTERED)
            : this(idxName, isUNIQUE, isCLUSTERED, false)
        {
        }

        /// <summary>
        /// 创建指定聚焦、重复与否的索引
        /// </summary>
        /// <param name="idxName">索引名称</param>
        /// <param name="isUNIQUE">是否不重复</param>
        /// <param name="isCLUSTERED">是否聚焦</param>
        /// <param name="isDesc">是否建立倒序索引</param>
        public SqlIndexConfig(string idxName, bool isUNIQUE, bool isCLUSTERED, bool isDesc)
        {
            IndexName = idxName;
            IsUnique = isUNIQUE;
            IsClustered = isCLUSTERED;
            IsDescIndex = isDesc;
        }

        /// <summary>
        /// 索引名称
        /// </summary>
        public string IndexName { get; set; }

        /// <summary>
        /// 是否是不重复的索引
        /// </summary>
        public bool IsUnique { get; set; }

        /// <summary>
        /// 是否是聚焦索引
        /// </summary>
        public bool IsClustered { get; set; }

        /// <summary>
        /// 是否倒序建立的索引
        /// </summary>
        public bool IsDescIndex { get; set; }

        private SqlIndexColumn[] _cIndex = new SqlIndexColumn[0];
        /// <summary>
        /// 获取或设置当前索引所配置的列
        /// </summary>
        public SqlIndexColumn[] ColumnIndex 
        {
            get { return _cIndex; }
            set { _cIndex = value; }
        }

    }
    
    /// <summary>
    /// SQL表中的索引列配置
    /// </summary>
    [Serializable]
    public class SqlIndexColumn
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SqlIndexColumn"/> class.
        /// </summary>
        /// <param name="colName">列名称</param>
        /// <param name="isDesc">是否倒序建立</param>
        public SqlIndexColumn(string colName, bool isDesc)
        {
            ColumnName = colName;
            IsDesc = isDesc;
        }

        /// <summary>
        /// 新建一个默认顺序的索引列
        /// </summary>
        /// <param name="colName">列名称</param>
        public SqlIndexColumn(string colName)
           : this (colName, false)
        { 
        
        }

        /// <summary>
        /// 列名称
        /// </summary>
        public string ColumnName { get; set; }

        /// <summary>
        /// 是否倒序建立索引
        /// </summary>
        public bool IsDesc { get; set; }

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString()
        {
            return string.Format("{0} {1}", ColumnName, IsDesc ? "Desc" : "ASC");
        }
    }

    /// <summary>
    /// SQL表中约束
    /// </summary>
    [Serializable]
    public class SqlConstraint
    {
        /// <summary>
        /// SQL约束实例
        /// </summary>
        /// <param name="name">约束名称</param>
        /// <param name="exp">约束设置的表达式</param>
        public SqlConstraint(string name, string exp)
        {
            ConstraintName = name;
            Expression = exp;
        }

        /// <summary>
        /// 约束名称
        /// </summary>
        public string ConstraintName { get; set; }

        /// <summary>
        /// 约束表达式
        /// </summary>
        public string Expression { get; set; }

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString()
        {
            return string.Format("{0} {1}", ConstraintName, Expression);
        }

    }

}
